#include <QtCore/QtGlobal>
#include "PluginManager.h"
#include "PluginHelper.h"

#include <QtCore/QLibrary>
#include <UtilFunc/PluginInc.h>
#include <UtilFunc/LoadDllHelper.h>
#include <QDebug>

static StringMapHandle		g_stringMapHandle;
HANDLE  funPluginModuleInterface(const wchar_t* dllName)
{
	QString  strDllName = QString::fromWCharArray(dllName);
	if(g_stringMapHandle.contains(strDllName))
	{
		return g_stringMapHandle[strDllName];
	}
	return NULL;
}

QPluginManager::QPluginManager(void)
{
	
}

QPluginManager::~QPluginManager(void)
{
}

bool QPluginManager::unLoadPlugin( bool all /*= false*/ )
{
	bool bRes = false;
	int  nTotal = 0;
	int  nSuccess = 0;
	foreach(LoadDllHelper *pDll,m_stringMapDll){
		if(pDll)
		{
			pDll->Unload();
			FREEMEMORY(pDll);
			bRes = true;
			nSuccess ++;
		}

		nTotal++;
	}

	m_stringMapDll.clear();

	//LogWriter::getLogCenter()->PrintLog(bRes,"Total UnLoad Plugin Success: %d,Failed: %d",nSuccess,nTotal - nSuccess);

	return true;
}

bool QPluginManager::unLoadPlugin( const wchar_t* wfilename )
{
	wchar_t	 wchAppPath[MAX_PATH]={0};  
	wchar_t  wchFullPath[MAX_PATH]={0};
	wchar_t	 wchDllName[MAX_PATH]={0};
	wchar_t  wchKeyName[MAX_PATH]={0};
	char	 chDllName[MAX_PATH]={0};
	PluginHelper::GetLocalAppDataPath(wchAppPath);
	PluginHelper::GetFileFullPath(wfilename,wchFullPath);
	PluginHelper::GetFileNameFromFullPath(wchFullPath,wchDllName);
	PluginHelper::GetFileNameFromFullPath(wchFullPath,wchKeyName,true);

	bool bRes = false;
	QString strKeyName = QString::fromWCharArray(wchKeyName);
	QCommonBase::StringToChar(strKeyName,chDllName);

	
	if(m_stringMapDll.contains(strKeyName))
	{
		LoadDllHelper *pDll = m_stringMapDll[strKeyName];
		if(pDll)
		{
			AppModule* pModule = (AppModule*)getAppModule(wfilename);
			if(pModule)
				pModule->UnInitModule();
			pDll->Unload();
			FREEMEMORY(pDll);
			bRes = true;
		}
		else
		{
			bRes = false;
		}
		m_stringMapDll.remove(strKeyName);

	}

	//LogWriter::getLogCenter()->PrintLog(bRes,"%s UnLoad %s",chDllName,bRes ?"Success":"Error");

	return bRes;
}

bool QPluginManager::loadPlugin( const wchar_t* wfilename )
{
	wchar_t	 wchAppPath[MAX_PATH]={0};
	wchar_t  wchFullPath[MAX_PATH]={0};
	wchar_t	 wchDllName[MAX_PATH]={0};
	wchar_t  wchKeyName[MAX_PATH]={0};
	char	 chDllName[MAX_PATH]={0};
	PluginHelper::GetLocalAppDataPath(wchAppPath);
	PluginHelper::GetFileFullPath(wfilename,wchFullPath);
	PluginHelper::GetFileNameFromFullPath(wchFullPath,wchDllName);
	PluginHelper::GetFileNameFromFullPath(wchFullPath,wchKeyName,true);
	
	bool bRes = false;
	QString strKeyName = QString::fromWCharArray(wchKeyName);
	QCommonBase::StringToChar(strKeyName,chDllName);
	if(m_stringMapDll.contains(strKeyName))
	{
		LoadDllHelper *pDll = m_stringMapDll[strKeyName];
		if(!pDll)
		{
			m_stringMapDll[strKeyName] = new LoadDllHelper(wchFullPath);
			bRes = m_stringMapDll[strKeyName]->GetHandle() ? true:false;
		}

		else if(pDll && !pDll->GetHandle())
		{
			FREEMEMORY(pDll);
			m_stringMapDll[strKeyName] = new LoadDllHelper(wchFullPath);
			bRes = m_stringMapDll[strKeyName]->GetHandle() ? true:false;
		}
	}
	else
	{
		m_stringMapDll[strKeyName] = new LoadDllHelper(wchFullPath);
		bRes = m_stringMapDll[strKeyName]->GetHandle() ? true:false;
	}
 	if(bRes)
 	{
		HANDLE hInstance = getModuleInterface(wchKeyName);
		Q_ASSERT(hInstance);
		if(hInstance == NULL) bRes = false;
		if(hInstance)
		{
			AppModule* pModule = (AppModule* )getAppModule(wchKeyName);
			Q_ASSERT(pModule);
 		//	if(pModule)
 		//	{
 		//		pModule->RegisterModule(this);			
 		//	}
		}
 		
 	}

	//LogWriter::getLogCenter()->PrintLog(bRes,"%s Load %s",chDllName,bRes ?"Success":"Error");
	return bRes;
}

bool QPluginManager::initPluginModule( HANDLE pInstance)
{
	AppModule* pModule = (AppModule*) pInstance;
	Q_ASSERT(pModule);
	if(pModule)
		pModule->InitModule(funPluginModuleInterface);
	return true;
}

void* QPluginManager::getAppModule( const wchar_t* dllname )
{
	FUNC_GETREGISTERBANK pfnBank = (FUNC_GETREGISTERBANK)GetProcAddress(GetModuleHandleW(dllname), "GetAppModule");
	Q_ASSERT(pfnBank != NULL);
	Q_ASSERT( (*pfnBank)() != NULL);
	if( (*pfnBank)() == NULL) return NULL;

	AppModule* pModule = (*pfnBank)();
	if(pModule)
		pModule->InitModule(funPluginModuleInterface);

	return pfnBank ? (*pfnBank)() : NULL;
}

HANDLE QPluginManager::getModuleInterface( const wchar_t* interfaceName )
{
	char chFileName[MAX_PATH]={0};
	PluginHelper::WCharToChar(interfaceName,chFileName);
	QString  strFileName = QString(chFileName);

	FUNC_GETREGISTERBANK  pfnBank = (FUNC_GETREGISTERBANK)GetProcAddress(GetModuleHandleW(interfaceName), "GetAppModuleInterface");

	Q_ASSERT(pfnBank != NULL);
	
	Q_ASSERT((*pfnBank)() != NULL);
	if((*pfnBank)())
		g_stringMapHandle[strFileName] = (*pfnBank)() ;

	//LogWriter::getLogCenter()->PrintLog(LOG_INFO,"%s , %0Xd\r\n" , chFileName ,(*pfnBank));

	return pfnBank ? (*pfnBank)() : NULL;
}

HANDLE QPluginManager::getModuleFun( const wchar_t* dllName )
{
	char chFileName[MAX_PATH]={0};
	PluginHelper::WCharToChar(dllName,chFileName);
	QString  strFileName = QString(chFileName);

	if(g_stringMapHandle.contains(strFileName))
		return g_stringMapHandle[strFileName];
	return NULL;
}
